This is cross-posted here from Israel.pm where I have yet to receive an answer.
I'm trying to process the directory components of a path (as an array) so that:
If the processing is to keep only the directories after "long-dir" then:
UNIX : /hello/there/long-dir/another/myfile.txt ==> another/myfile.txt DOS : C:\Hello\There\Long-Dir\Another\myfile.txt ==> another\myfile.txt UNIX: ./hi/long-dir/another/myfile.txt ==> another/myfile.txt DOS: .\hi\long-dir\another\myfile.txt ==> another\myfile.txt
To do this I turned to File::Spec and File::Basename and wrote the following code which seems insanely complicated. I marked the place where I do the actual processing using a callback:
use File::Spec; use File::Basename; sub _process_filename_dirs { my ($self, $fn, $callback) = @_; my $basename = basename($fn); my $dirpath = dirname($fn); my ($volume, $directories, $filename) = File::Spec->splitpath($dirpath, 1); # The actual manipulation. my $dirs = $callback->([File::Spec->splitdir($directories)]); my $final_dir = File::Spec->catpath( $volume, File::Spec->catdir(@$dirs), $filename ); if ($final_dir eq "") { return $basename; } else { return File::Spec->catfile( $final_dir, $basename ); } }
And so far I checked it works only on UNIXes (Linux in my case) and on relative paths.
So my questions are:
I should note that this hairiness is not limited to Perl. Common Lisp has a built-in portable path-manipulation abstraction that's also relatively complicated. See the "File and File I/O Chapter" and the a Portable Pathname library chapter